﻿using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AT.IBMS.Framework.Controls.Designe;

namespace AT.IBMS.Framework.Controls
{

    /// <summary>
    /// 用于ASP.NET Web应用程序中对数据进行分页的的服务器控件。
    /// </summary>
    /// <remarks>
    ///       不同于DataGrid或GridView等带分页功能的数据绑定控件，AspNetPager分页控件本身并不显示任何数据，而只显示分页导航元素，数据在页面上的显示方式与该控件无关。AspNetPager分页控件可以为GridView、DataGrid、DataList、Repeater以及自定义的数据绑定控件进行分页。AspNetPager不仅仅是一个分页控件，它还可以实现如图片浏览等程序中的前一页后一页等导航功能。
    ///       <p>AspNetPager控件的分页方法和GridView非常相似，但AspNetPager的分页功能更为灵活、强大。AspNetPager分页控件不仅仅支持默认的PostBack方式分页，它还支持通过Url来实现分页以及Url重写功能，这使得访问者可以直接输入相应的Url来访问任何页面，并且搜索引擎也可以直接检索每个页面，若使用DataGrid或GridView等.net框架自带的数据绑定控件的分页功能，这些是无法实现的。</p><p>
    ///         要使用 AspNetPager 分页控件，必须最少指定它的 <see cref="RecordCount" /> 属性的值，另外如果需要，指定并编写 <see cref="PageChanging"/> 或 <see cref="PageChanged" /> 事件的处理程序，可以在PageChanging事件处理程序中取消分页事件，在PageChanged事件处理程序中绑定数据或实现自定义的数据呈现逻辑。
    ///         <see cref="RecordCount" /> 属性指定要分页的所有数据的总项数，若未指定该值或该值小于等于 <see cref="PageSize" /> ，即要分页的数据只有一页，则AspNetPager控件默认会自动隐藏而不显示任何内容，若需在只有一页数据的情况下显示AspNetPager分页控件，可以将它的AlwaysShow属性设为true即可。
    ///        </p></remarks>
    ///     <example>
    ///       以下示例说明如何用AspNetPager对Repeater进行分页。
    ///       <code>
    ///         <![CDATA[
    /// <%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer" TagPrefix="webdiyer" %>
    /// <%@Import NameSpace="System.Data"%>
    /// <%@Import NameSpace="System.Data.SqlClient"%>
    /// <script runat="server" Language="C#">
    /// void Page_Load(object sender, EventArgs e)
    ///     {
    ///         if (!IsPostBack)
    ///         {
    ///             int totalOrders = (int)SqlHelper.ExecuteScalar(CommandType.StoredProcedure, "P_GetOrderNumber");
    ///             AspNetPager1.RecordCount = totalOrders;
    ///             bindData();
    ///         }
    ///     }
    /// 
    ///  void bindData()
    ///     {
    ///         Repeater1.DataSource = SqlHelper.ExecuteReader(CommandType.StoredProcedure,"P_GetPagedOrders2005",
    ///             new SqlParameter("@startIndex", AspNetPager1.StartRecordIndex),
    ///             new SqlParameter("@pageSize", AspNetPager1.PageSize));
    ///         Repeater1.DataBind();
    ///     }
    /// 
    ///  void AspNetPager1_PageChanged(object src, EventArgs e)
    ///     {
    ///         bindData();
    ///     }
    /// </script>
    /// <HTML><HEAD>
    /// <TITLE> AspNetPager Samples </TITLE>
    /// <META NAME="Author" CONTENT="Webdiyer (www.webdiyer.com)">
    /// </HEAD>
    /// 
    /// <BODY>
    /// <form runat="server">
    ///         <asp:Repeater ID="Repeater1" runat="server">
    ///         <HeaderTemplate>
    ///         <table width="100%" border="1" cellspacing="0" cellpadding="4" style="border-collapse:collapse">
    ///         <tr style="backGround-color:#CCCCFF"><th style="width:15%"><asp:Literal ID="Literal1" runat="server" Text="<%$Resources:LocalizedText,orderid%>" /></th><th style="width:15%"><asp:Literal ID="Literal3" runat="server" Text="<%$Resources:LocalizedText,orderdate%>" /></th><th style="width:30%"><asp:Literal ID="Literal5" runat="server" Text="<%$Resources:LocalizedText,companyname%>" /></th><th style="width:20%"><asp:Literal ID="Literal2" runat="server" Text="<%$Resources:LocalizedText,customerid%>" /></th><th style="width:20%"><asp:Literal ID="Literal4" runat="server" Text="<%$Resources:LocalizedText,employeename%>" /></th></tr>
    ///         </HeaderTemplate>
    ///         <ItemTemplate>
    ///         <tr style="background-color:#FAF3DC">
    ///         <td><%#DataBinder.Eval(Container.DataItem,"orderid")%></td>
    ///         <td><%#DataBinder.Eval(Container.DataItem,"orderdate","{0:d}")%></td>
    ///         <td><%#DataBinder.Eval(Container.DataItem, "companyname")%></td>
    ///         <td><%#DataBinder.Eval(Container.DataItem,"customerid")%></td>
    ///         <td><%#DataBinder.Eval(Container.DataItem,"employeename")%></td>
    ///         </tr>
    ///         </ItemTemplate>
    ///         <FooterTemplate>
    ///         </table>
    ///         </FooterTemplate>
    ///         </asp:Repeater>
    ///   <webdiyer:AspNetPager ID="AspNetPager1" runat="server" Width="100%" HorizontalAlign="right" PageSize="8" OnPageChanged="AspNetPager1_PageChanged">
    ///         </webdiyer:AspNetPager>
    ///         </form>
    /// </BODY>
    /// </HTML>
    ///  ]]>
    ///       </code><p>该示例所用的Sql Server存储过程代码如下（仅适用于SQL Server 2005）：</p><code>
    /// <![CDATA[
    /// CREATE PROCEDURE P_GetPagedOrders2005
    ///     @startIndex INT, 
    ///     @pageSize INT 
    /// AS
    /// begin
    /// WITH orderList AS ( 
    /// SELECT ROW_NUMBER() OVER (ORDER BY O.orderid DESC)AS Row, O.orderid,O.orderdate,O.customerid,C.CompanyName,E.FirstName+' '+E.LastName as EmployeeName 
    /// from orders O
    /// left outer join Customers C
    /// on O.CustomerID=C.CustomerID
    /// left outer join Employees E
    /// on O.EmployeeID=E.EmployeeID)
    /// 
    /// SELECT orderid,orderdate,customerid,companyName,employeeName
    /// FROM orderlist
    /// WHERE Row between @startIndex and @startIndex+@pageSize-1
    /// end
    ///  ]]>
    /// </code>
    ///       </example>
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    [DefaultProperty("PageSize")]
    [DefaultEvent("PageChanged")]
    [ParseChildren(false)]
    [PersistChildren(false)]
    [Designer(typeof(PagerDesigner))]
    [ANPDescription("desc_AspNetPager")]
    [ToolboxData("<{0}:AspNetPager runat=server></{0}:AspNetPager>")]
    public partial class AspNetPager : Panel, INamingContainer, IPostBackEventHandler, IPostBackDataHandler
    {

        /// <summary>
        /// 重写 <see cref="System.Web.UI.Control.OnInit" /> 方法。
        /// </summary>
        /// <param name="e">包含事件数据的 <see cref="EventArgs" /> 对象。</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (null != CloneFrom && string.Empty != CloneFrom.Trim())
            {
                AspNetPager ctrl = Parent.FindControl(CloneFrom) as AspNetPager;
                if (null == ctrl)
                {
                    string errStr = SR.GetString("clonefromexeption") ??
                                    "The control \" %controlID% \" does not exist or is not of type Wuqi.Webdiyer.AspNetPager!";
                    throw new ArgumentException(errStr.Replace("%controlID%", CloneFrom), "CloneFrom");
                }
                if (null != ctrl.cloneFrom && this == ctrl.cloneFrom)
                {
                    string errStr = SR.GetString("recusiveclonefrom") ??
                                    "Invalid value for the CloneFrom property, AspNetPager controls can not to be cloned recursively!";
                    throw new ArgumentException(errStr, "CloneFrom");
                }
                cloneFrom = ctrl;
                CssClass = cloneFrom.CssClass;
                Width = cloneFrom.Width;
                Height = cloneFrom.Height;
                HorizontalAlign = cloneFrom.HorizontalAlign;
                BackColor = cloneFrom.BackColor;
                BackImageUrl = cloneFrom.BackImageUrl;
                BorderColor = cloneFrom.BorderColor;
                BorderStyle = cloneFrom.BorderStyle;
                BorderWidth = cloneFrom.BorderWidth;
                Font.CopyFrom(cloneFrom.Font);
                ForeColor = cloneFrom.ForeColor;
                EnableViewState = cloneFrom.EnableViewState;
                Enabled = cloneFrom.Enabled;
            }
        }

        /// <summary>
        /// 重写 <see cref="System.Web.UI.Control.OnLoad" /> 方法。
        /// </summary>
        /// <param name="e">包含事件数据的 <see cref="EventArgs" /> 对象。</param>
        protected override void OnLoad(EventArgs e)
        {
            if (UrlPaging)
            {
                currentUrl = Page.Request.Path;
                queryString = Page.Request.ServerVariables["Query_String"];
                if (!Page.IsPostBack && cloneFrom == null)
                {
                    int index;
                    int.TryParse(Page.Request.QueryString[UrlPageIndexName], out index);
                    if (index <= 0)
                        index = 1;
                    else if (ReverseUrlPageIndex)
                        index = PageCount - index + 1;
                    PageChangingEventArgs args = new PageChangingEventArgs(index);
                    OnPageChanging(args);
                }
            }
            else
            {
                inputPageIndex = Page.Request.Form[UniqueID + "_input"];
            }
            base.OnLoad(e);
        }

        /// <summary>
        /// 重写<see cref="System.Web.UI.Control.OnPreRender" />方法。
        /// </summary>
        /// <param name="e">包含事件数据的 <see cref="EventArgs" /> 对象。</param>
        protected override void OnPreRender(EventArgs e)
        {
            if (PageCount > 1)
            {
                if ((ShowPageIndexBox == ShowPageIndexBox.Always) || (ShowPageIndexBox == ShowPageIndexBox.Auto && PageCount >= ShowBoxThreshold))
                {
                    StringBuilder sb = new StringBuilder("<script language=\"Javascript\" type=\"text/javascript\"><!--\n");
                    if (UrlPaging)
                    {
                        sb.Append("function ANP_goToPage(boxEl){if(boxEl!=null){var pi;if(boxEl.tagName==\"SELECT\")");
                        sb.Append("{pi=boxEl.options[boxEl.selectedIndex].value;}else{pi=boxEl.value;}");
                        if (string.IsNullOrEmpty(UrlPagingTarget))
                            sb.Append("location.href=\"").Append(GetHrefString(-1)).Append("\"");
                        else
                            sb.Append("window.open(\"").Append(GetHrefString(-1)).Append("\",\"").Append(UrlPagingTarget).Append("\")");
                        sb.Append(";}}\n");
                    }
                    if (PageIndexBoxType == PageIndexBoxType.TextBox)
                    {
                        string ciscript = SR.GetString("checkinputscript");
                        if (ciscript != null)
                        {
                            ciscript = ciscript.Replace("%PageIndexOutOfRangeErrorMessage%", PageIndexOutOfRangeErrorMessage);
                            ciscript = ciscript.Replace("%InvalidPageIndexErrorMessage%", InvalidPageIndexErrorMessage);
                        }
                        sb.Append(ciscript).Append("\n");
                        string keyScript = SR.GetString("keydownscript");
                        sb.Append(keyScript);
                    }
                    sb.Append("\n--></script>");
                    Type ctype = GetType();
                    ClientScriptManager cs = Page.ClientScript;
                    if (!cs.IsClientScriptBlockRegistered(ctype, "anp_script"))
                        cs.RegisterClientScriptBlock(ctype, "anp_script", sb.ToString());
                }
            }
            base.OnPreRender(e);
        }

        /// <summary>
        /// 重写<see cref="System.Web.UI.WebControls.WebControl.AddAttributesToRender" /> 方法，将需要呈现的 HTML 属性和样式添加到指定的 <see cref="System.Web.UI.HtmlTextWriter" /> 中
        /// </summary>
        /// <param name="writer"><see cref="System.Web.UI.HtmlTextWriter" />，表示要在客户端呈现 HTML 内容的输出流。</param>
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            if (Page != null && !UrlPaging)
                Page.VerifyRenderingInServerForm(this);
            base.AddAttributesToRender(writer);
        }

        /// <summary>
        /// 重写 <see cref="System.Web.UI.WebControls.WebControl.RenderBeginTag" /> 方法，将 <see cref="AspNetPager" /> 控件的 HTML 开始标记输出到指定的 <see cref="System.Web.UI.HtmlTextWriter" /> 编写器中。
        /// </summary>
        /// <param name="writer"><see cref="System.Web.UI.HtmlTextWriter" />，表示要在客户端呈现 HTML 内容的输出流。</param>
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            bool showPager = (PageCount > 1 || (PageCount <= 1 && AlwaysShow));
            writer.WriteLine();
            //writer.Write("<!-- ");
            //writer.Write("AspNetPager " + VersionNumber + "  Copyright:2003-2010 Webdiyer (www.webdiyer.com)");
            //writer.WriteLine(" -->");
            if (!showPager)
            {
                writer.Write("<!--");
                writer.Write(SR.GetString("autohideinfo"));
                writer.Write("-->");
            }
            else
            {
                base.RenderBeginTag(writer);
            }
        }

        /// <summary>
        /// 重写 <see cref="System.Web.UI.WebControls.WebControl.RenderEndTag" /> 方法，将 <see cref="AspNetPager" /> 控件的 HTML 结束标记输出到指定的 <see cref="System.Web.UI.HtmlTextWriter" /> 编写器中。
        /// </summary>
        /// <param name="writer"><see cref="System.Web.UI.HtmlTextWriter" />，表示要在客户端呈现 HTML 内容的输出流。</param>
        public override void RenderEndTag(HtmlTextWriter writer)
        {

            if (PageCount > 1 || (PageCount <= 1 && AlwaysShow))
            {
                base.RenderEndTag(writer);
            }

            writer.WriteLine();
            //writer.Write("<!-- ");
            //writer.Write("AspNetPager " + VersionNumber + "  Copyright:2003-2010 Webdiyer (www.webdiyer.com)");
            //writer.WriteLine(" -->");
            //writer.WriteLine();
        }

        /// <summary>
        /// 重写 <see cref="System.Web.UI.WebControls.WebControl.RenderContents" /> 方法，将控件的内容呈现到指定 <see cref="System.Web.UI.HtmlTextWriter" /> 的编写器中。
        /// </summary>
        /// <param name="writer"><see cref="System.Web.UI.HtmlTextWriter" />，表示要在客户端呈现 HTML 内容的输出流。</param>
        protected override void RenderContents(HtmlTextWriter writer)
        {
            if (PageCount <= 1 && !AlwaysShow)
                return;
            writer.Indent = 0;
            if (ShowCustomInfoSection != ShowCustomInfoSection.Never)
            {
                if (LayoutType == LayoutType.Table)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Width, "100%");
                    writer.AddAttribute(HtmlTextWriterAttribute.Style, Style.Value);
                    if (Height != Unit.Empty)
                        writer.AddStyleAttribute(HtmlTextWriterStyle.Height, Height.ToString());
                    writer.AddAttribute(HtmlTextWriterAttribute.Border, "0");
                    writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
                    writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
                    writer.RenderBeginTag(HtmlTextWriterTag.Table); //<table>
                    writer.RenderBeginTag(HtmlTextWriterTag.Tr); //<tr>
                }
                if (ShowCustomInfoSection == ShowCustomInfoSection.Left)
                {
                    RenderCustomInfoSection(writer);
                    RenderNavigationSection(writer);
                }
                else
                {
                    RenderNavigationSection(writer);
                    RenderCustomInfoSection(writer);
                }
                if (LayoutType == LayoutType.Table)
                {
                    writer.RenderEndTag(); //</tr>
                    writer.RenderEndTag(); //</table>
                }
            }
            else
                RenderPagingElements(writer);
        }

    }

    #region PageChangingEventHandler Delegate

    /// <summary>
    /// 表示处理 <see cref="AspNetPager.PageChanging" /> 事件的方法。
    /// </summary>
    public delegate void PageChangingEventHandler(object src, PageChangingEventArgs e);

    #endregion

}
